package git.soulbgm.common.realm;

import git.soulbgm.common.constant.RedisKeyConstant;
import git.soulbgm.common.exception.TokenAuthenticationException;
import git.soulbgm.common.token.JwtToken;
import git.soulbgm.pojo.PrincipalUser;
import git.soulbgm.utils.JsonUtil;
import git.soulbgm.utils.JwtUtil;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @author SoulBGM
 * @version 1.0
 * @date 2019/11/6 17:20
 */
@Component
public class JwtRealm extends AuthorizingRealm {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public String getName() {
        return "jwtRealm";
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        PrincipalUser user = (PrincipalUser) principals.getPrimaryPrincipal();
        if (user != null) {
            simpleAuthorizationInfo.setRoles(user.getRoleSet());
            simpleAuthorizationInfo.setStringPermissions(user.getUrlSet());
        }
        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String jwtToken = (String) token.getPrincipal();
        Map<String, Object> map = JwtUtil.getBody(jwtToken);
        Integer id = (Integer) map.get("id");
        String s = redisTemplate.opsForValue().get(RedisKeyConstant.TOKEN + id);
        PrincipalUser user = JsonUtil.parse(s, PrincipalUser.class);

        if (user != null) {
            return new SimpleAuthenticationInfo(user, jwtToken, getName());
        }

        throw new TokenAuthenticationException("令牌已过期或不正确");
    }
}
